<!------------------------------------------------------------- Keyence ------------------------------------------------->
<script type="text/html" data-template-name="Keyence">
    <!-- name -->
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> name</label>
        <input type="text" id="node-input-name" placeholder="name">
    </div>
    <!-- server -->
    <div class="form-row">
        <label for="node-input-server"><i class="fa fa-globe"></i> server</label>
        <input type="text" id="node-input-server" placeholder="ip.address" style="width:45%"> port
        <input type="text" id="node-input-port" style="width:80px" placeholder="ip.port">
    </div>
    <!-- retun -->
    <div class="form-row">
        <label for="node-input-out"><i class="fa fa-sign-out"></i> return</label>
        <select type="text" id="node-input-out" style="width:45%;">
        <option value="time">A single connection at a specified time</option>
        <!-- <option value="char">When a character is received as</option> -->
        <!-- <option value="count">Specify the number of characters</option> -->
        <option value="sit">stay connected</option>
        <!-- <option value="immed">No need to wait for a reply</option> -->
    </select>
        <input type="text" id="node-input-splitc" style="width:50px;">
        <span id="node-units"></span>
    </div>
    <!-- model -->
    <div class="form-row border_bottom">
        <label for="node-input-model"><i class="fa fa-dot-circle-o"></i> model</label>
        <select id="node-input-model" style="width:20%;">
        <option value="read">read address</option>
        <option value="write">write address</option>
    </select>
        <span style="margin-left:70px;"> wait<input style="width:15px;" type="checkbox" id="node-input-wait_check"></span>
        <span class="interval_sw_time"><input style="width:17%;" type="text" id="node-input-interval_sw_time"
            placeholder="interval time"> ms</span>
    </div>
    <!-- read data mode -->
    <div class="form-row">
        <ul class="RD">
            <li>
                <label for="node-input-RD_Addr"></i> initial address</label>
                <input style="width:20%;" type="text" id="node-input-RD_Addr" placeholder="start address">
            </li>
            <li>
                <label for="node-input-RD_Num"> read bits</lab el>
                <input style="width:20%;" type="text" id="node-input-RD_Num" placeholder="number">
            </li>
        </ul>
    </div>
    <!-- write data mode -->
    <div class="form-row">
        <ul class="WR">
            <li><label for="node-input-WR_Addr"></i> initial address</label>
                <input style="width:20%;" type="text" id="node-input-WR_Addr" placeholder="start address">
            </li>
            <li> <label for="node-input-WR_Value"> write value</label>
                <input style="width:20%;" type="text" id="node-input-WR_Value" placeholder="value">
            </li>
        </ul>
    </div>
    <!------------------------------------------------------------------- switch --------------------------------------------------------->
    <!-- Attributes -->
    <div class="form-row">
        <input type="hidden" id="node-input-outputs" />
    </div>
    <div class="form-row node-input-rule-container-row">
        <ol id="node-input-rule-container"></ol>
    </div>
    </div>
</script>

<!------------------------------------------------------------- Read address ------------------------------------------------->
<script type="text/html" data-template-name="Read address">
    <!-- server -->
    <div class="form-row">
        <label for="node-input-server"><i class="fa fa-globe"></i> server</label>
        <input type="text" id="node-input-server" placeholder="ip.address" style="width:45%"> port
        <input type="text" id="node-input-port" style="width:85px" placeholder="ip.port">
    </div>
    </div>
    <!-- read data mode -->
    <div class="form-row">
        <ul class="RD">
            <li>
                <label for="node-input-interval_tcp_time"></i> Timing</label>
                <input style="width:20%;" type="text" id="node-input-interval_tcp_time" placeholder="interval time"> ms
            </li>
            <li>
                <label for="node-input-RD_Addr"></i> initial address</label>
                <input style="width:20%;" type="text" id="node-input-RD_Addr" placeholder="start address">
            </li>
            <li>
                <label for="node-input-RD_Num"> read bits</label>
                <input style="width:20%;" type="text" id="node-input-RD_Num" placeholder="number">
            </li>
        </ul>
    </div>
    <!------------------------------------------------------------------- switch --------------------------------------------------------->

</script>

<script type="text/javascript">
    (function() {
        // Condition option object
        var ports_addr = [];
        var operators = [{
                v: "eq",
                t: "==",
                kind: 'V'
            }, {
                v: "neq",
                t: "!=",
                kind: 'V'
            }, {
                v: "lt",
                t: "<",
                kind: 'V'
            }, {
                v: "lte",
                t: "<=",
                kind: 'V'
            }, {
                v: "gt",
                t: ">",
                kind: 'V'
            }, {
                v: "gte",
                t: ">=",
                kind: 'V'
            },
            //  {
            //     v: "hask",
            //     t: "switch.rules.hask",
            //     kind: 'V'
            // }, {
            //     v: "btwn",
            //     t: "switch.rules.btwn",
            //     kind: 'V'
            // }, {
            //     v: "cont",
            //     t: "switch.rules.cont",
            //     kind: 'V'
            // }, {
            //     v: "regex",
            //     t: "switch.rules.regex",
            //     kind: 'V'
            // }, {
            //     v: "true",
            //     t: "switch.rules.true",
            //     kind: 'V'
            // }, {
            //     v: "false",
            //     t: "switch.rules.false",
            //     kind: 'V'
            // }, {
            //     v: "null",
            //     t: "switch.rules.null",
            //     kind: 'V'
            // }, {
            //     v: "nnull",
            //     t: "switch.rules.nnull",
            //     kind: 'V'
            // }, {
            //     v: "istype",
            //     t: "switch.rules.istype",
            //     kind: 'V'
            // }, {
            //     v: "empty",
            //     t: "switch.rules.empty",
            //     kind: 'V'
            // }, {
            //     v: "nempty",
            //     t: "switch.rules.nempty",
            //     kind: 'V'
            // }, {
            //     v: "head",
            //     t: "switch.rules.head",
            //     kind: 'S'
            // }, {
            //     v: "index",
            //     t: "switch.rules.index",
            //     kind: 'S'
            // }, {
            //     v: "tail",
            //     t: "switch.rules.tail",
            //     kind: 'S'
            // }, {
            //     v: "jsonata_exp",
            //     t: "switch.rules.exp",
            //     kind: 'O'
            // }, {
            //     v: "else",
            //     t: "switch.rules.else",
            //     kind: 'O'
            // }
        ];

        function clipValueLength(v) {
            if (v.length > 15) {
                return v.substring(0, 15) + "...";
            }
            return v;
        }

        function prop2name(key) {
            var result = RED.utils.parseContextKey(key);
            return result.key;
        }

        function getValueLabel(t, v) {
            if (t === 'str') {
                return '"' + clipValueLength(v) + '"';
            } else if (t === 'msg') {
                return t + "." + clipValueLength(v);
            } else if (t === 'flow' || t === 'global') {
                return t + "." + clipValueLength(prop2name(v));
            }
            return clipValueLength(v);
        }
        //////////////////////////////////////////////////////////////////////////////////////////////////// Register Keyence Node
        RED.nodes.registerType('Keyence', {
            color: "Skyblue",
            category: 'PLC',
            defaults: {
                // name
                name: {
                    value: ""
                },
                // server
                server: {
                    value: "",
                    required: true
                },
                // The port number
                port: {
                    value: "",
                    validate: RED.validators.regex(/^(\d*|)$/),
                    required: true

                },
                // output mode
                out: {
                    value: "time",
                    required: true
                },
                // Division rules
                splitc: {
                    value: "0",
                    required: true
                },
                // model
                model: {
                    value: "read",
                    required: true
                },
                // model
                wait_check: {
                    value: false,
                },
                //Timing period
                interval_sw_time: {
                    value: 1000,
                    validate: RED.validators.regex(/^\+?[1-9]\d*$/),
                },
                //Read PLC start address
                RD_Addr: {
                    value: "",
                    validate: function(v) {
                        return (this.model != "read") || v.length > 0;
                    }
                },
                //Get the number of digits
                RD_Num: {
                    value: "",
                    validate: function(v) {
                        return (this.model != "read") || v.length > 0;
                    }
                },
                //write address
                WR_Addr: {
                    value: "",
                    validate: function(v) {
                        return (this.model != "write") || v.length > 0;
                    }
                },
                //write value
                WR_Value: {
                    value: "",
                    validate: function(v) {
                        return (this.model != "write") || v.length > 0;
                    }
                },
                /////////////////////////////////////////////////// switch
                // input property
                property: {
                    value: "payload",
                    required: true,
                    validate: RED.validators.typedInput("propertyType")
                },
                propertyType: {
                    value: "msg"
                },
                rules: {
                    value: [{
                        t: "neq",
                        v: "",
                        vt: "str"
                    }]
                },
                checkall: {
                    value: "true",
                    required: true
                },
                repair: {
                    value: false
                },
                outputs: {
                    value: 1
                },
            },
            inputs: 1,
            outputs: 1,
            outputLabels: function(index) {
                var rule = this.rules[index];
                var label = "";
                if (rule) {
                    for (var i = 0; i < operators.length; i++) {
                        if (operators[i].v === rule.t) {
                            label = /^switch/.test(operators[i].t) ? this._(operators[i].t) : operators[i].t;
                            break;
                        }
                    }
                    if ((rule.t === 'btwn') || (rule.t === 'index')) {
                        label += " " + getValueLabel(rule.vt, rule.v) + " & " + getValueLabel(rule.v2t, rule.v2);
                    } else if (rule.t !== 'true' && rule.t !== 'false' && rule.t !== 'null' && rule.t !== 'nnull' && rule.t !== 'empty' && rule.t !== 'nempty' && rule.t !== 'else') {
                        label += " " + getValueLabel(rule.vt, rule.v);
                    }
                    return label;
                }
            },
            icon: "bridge-dash.svg",
            label: function() {
                return this.name || 'Keyence';
            },
            labelStyle: function() {
                return this.name ? "node_label_italic" : "";
            },
            // Called before the dialog is displayed
            oneditprepare: function() {
                var node = this;
                var previous = null;
                var previousValueType = {
                    value: "prev",
                    label: this._("switch.previous"),
                    hasValue: false
                };
                /////////////////////button
                // if ($("#node-input-RD_Addr").val() && $("#node-input-RD_Num").val()) {
                //     $('.red-ui-editableList-addButton').css("display", "block", "!important")
                // } else {
                //     $('.red-ui-editableList-addButton').css("display", "none", "!important")
                // }
                //Address selection
                if ($("#node-input-RD_Num").val() && $("#node-input-RD_Addr").val()) {
                    ports_addr = [];
                    for (var i = 0; i < Number($("#node-input-RD_Num").val()); i++) {
                        ports_addr.push(Number($("#node-input-RD_Addr").val()) + i);
                    };
                }
                ////////////////////////////port
                $("#node-input-out").on('focus', function() {
                    previous = this.value;
                }).on("change", function() {
                    $("#node-input-splitc").show();
                    if (previous === null) {
                        previous = $("#node-input-out").val();
                    }
                    if ($("#node-input-out").val() == "char") {
                        if (previous != "char") {
                            $("#node-input-splitc").val("\\n");
                        }
                        $("#node-units").text("");
                    } else if ($("#node-input-out").val() == "time") {
                        if (previous != "time") {
                            $("#node-input-splitc").val("0");
                        }
                        // millisecond
                        $("#node-units").text(RED._("node-red:tcpin.label.ms"));
                    } else if ($("#node-input-out").val() == "immed") {
                        if (previous != "immed") {
                            $("#node-input-splitc").val(" ");
                        }
                        $("#node-units").text("");
                        $("#node-input-splitc").hide();
                    } else if ($("#node-input-out").val() == "count") {
                        if (previous != "count") {
                            $("#node-input-splitc").val("12");
                        }
                        // character
                        $("#node-units").text(RED._("node-red:tcpin.label.chars"));
                    } else {
                        if (previous != "sit") {
                            $("#node-input-splitc").val(" ");
                        }
                        $("#node-units").text("");
                        $("#node-input-splitc").hide();
                    }
                });
                // read and write mode
                $("#node-input-model").on('focus', function() {
                    previous = this.value;
                }).on("change", function() {
                    if ($("#node-input-model").val() == "write") {
                        $(".RD").hide();
                        $(".WR").show();
                        $(".port").hide();
                    } else {
                        $(".WR").hide();
                        $(".RD").show();
                        $(".port").show(1000);

                    }
                });
                // wait mode
                $("#node-input-wait_check").on("click").on('change', function() {
                    // var checked = ($("#node-input-wait_check").prop("checked"));
                    if ($("#node-input-wait_check").prop("checked")) {
                        $(".interval_sw_time").show();
                        $("#node-input-wait_check").val(true);
                    } else {
                        $(".interval_sw_time").hide();
                        $("#node-input-wait_check").val(false);
                    }
                });
                // Number of output ports
                var outputCount = $("#node-input-outputs").val("{}");
                var andLabel = this._("switch.and");
                var caseLabel = this._("switch.ignorecase");
                //reset rule function
                function resizeRule(rule) {
                    //Tab width
                    var newWidth = rule.width();
                    //Tab Rules
                    var selectField = rule.find("select");
                    var type = selectField.val() || "";
                    var valueField = rule.find(".node-input-rule-value");
                    var typeField = rule.find(".node-input-rule-type-value");
                    var numField = rule.find(".node-input-rule-num-value");
                    var expField = rule.find(".node-input-rule-exp-value");
                    var keyField = rule.find(".node-input-rule-key-value");
                    var btwnField1 = rule.find(".node-input-rule-btwn-value");
                    var btwnField2 = rule.find(".node-input-rule-btwn-value2");
                    //Tab width
                    var selectWidth;
                    if (type.length < 4) {
                        selectWidth = 60;
                    } else if (type === "regex") {
                        selectWidth = 147;
                    } else {
                        selectWidth = 120;
                    }
                    selectField.width(selectWidth);
                    if ((type === "btwn") || (type === "index")) {
                        btwnField1.typedInput("width", (newWidth - selectWidth - 70));
                        btwnField2.typedInput("width", (newWidth - selectWidth - 70));
                    } else if ((type === "head") || (type === "tail")) {
                        numField.typedInput("width", (newWidth - selectWidth - 70));
                    } else if (type === "jsonata_exp") {
                        expField.typedInput("width", (newWidth - selectWidth - 70));
                    } else if (type === "istype") {
                        typeField.typedInput("width", (newWidth - selectWidth - 70));
                    } else {
                        if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else") {
                            // valueField.hide();
                        } else {
                            valueField.typedInput("width", (newWidth - selectWidth - 70));
                        }
                    }
                }
                //Build conditional box content
                $("#node-input-rule-container").css('min-height', '246px').css('min-width', '400px').editableList({
                    // Add button event
                    // addItem: function(row, index, data) {
                    addItem: function(container, i, opt) {
                        if (!opt.hasOwnProperty('r')) {
                            // New opt object rule
                            opt.r = {};
                        }
                        //opt.r rules
                        var rule = opt.r;
                        if (!rule.hasOwnProperty('t')) {
                            //opt.r.t condition select2
                            rule.t = 'eq';
                        }
                        if (!opt.hasOwnProperty('i')) {
                            //opt.r._i random integer
                            opt._i = Math.floor((0x99999 - 0x10000) * Math.random()).toString();
                        }
                        container.css({
                            overflow: 'hidden',
                            whiteSpace: 'nowrap',
                            disabled: 'disabled'
                        });
                        //add div to row
                        var row = $('<div/>').appendTo(container);
                        var row2 = $('<div/>', {
                            style: "padding-top: 5px; padding-left: 175px;"
                        }).appendTo(container);
                        var row3 = $('<div/>', {
                            style: "padding-top: 5px; padding-left: 102px;"
                        }).appendTo(container);
                        ////////////////////////////////////////////////////////////////////////////////////////////port module
                        //select1
                        var selectPort = $('<select/>', {
                            style: "margin-left: 5px; text-align: center;"
                        }).appendTo(row);
                        var portgroup = $('<optgroup/>', {
                            label: "Choose an address"
                        }).appendTo(selectPort);
                        for (var d in ports_addr) {
                            portgroup.append($("<option></option>").val(ports_addr[d]).text(ports_addr[d]));
                        }
                        /////////////////////////////////////////////////////////////////////////////////////////////////////
                        // select2
                        var selectField = $('<select/>', {
                            style: "width:120px; margin-left: 5px; text-align: center;"
                        }).appendTo(row);
                        var group0 = $('<optgroup/>', {
                            label: "value rules"
                        }).appendTo(selectField);
                        for (var d in operators) {
                            if (operators[d].kind === 'V') {
                                group0.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
                            }
                        }
                        // var group1 = $('<optgroup/>', {
                        //     label: "sequence rules"
                        // }).appendTo(selectField);
                        // for (var d in operators) {
                        //     if (operators[d].kind === 'S') {
                        //         group1.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
                        //     }
                        // }
                        for (var d in operators) {
                            if (operators[d].kind === 'O') {
                                selectField.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
                            }
                        }
                        //input3
                        function createValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'num',
                                types: ['msg', 'flow', 'global', 'str', 'num', 'jsonata', 'env', previousValueType]
                            });
                        }

                        function createNumValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-num-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'num',
                                types: ['flow', 'global', 'num', 'jsonata', 'env']
                            });
                        }

                        function createExpValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-exp-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'jsonata',
                                types: ['jsonata']
                            });
                        }

                        function createBtwnValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-btwn-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'num',
                                types: ['msg', 'flow', 'global', 'str', 'num', 'jsonata', 'env', previousValueType]
                            });
                        }

                        function createBtwnAndLabel() {
                            return $('<span/>', {
                                class: "node-input-rule-btwn-label"
                            }).text(" " + andLabel + " ").appendTo(row3);
                        }

                        function createBtwnValue2Field() {
                            return $('<input/>', {
                                class: "node-input-rule-btwn-value2",
                                type: "text",
                                style: "margin-left:2px;"
                            }).appendTo(row3).typedInput({
                                default: 'num',
                                types: ['msg', 'flow', 'global', 'str', 'num', 'jsonata', 'env', previousValueType]
                            });
                        }
                        //create
                        function createTypeValueField() {
                            return $('<input/>', {
                                class: "node-input-rule-type-value",
                                type: "text",
                                style: "margin-left: 5px;"
                            }).appendTo(row).typedInput({
                                default: 'string',
                                types: [{
                                    value: "string",
                                    label: RED._("common.type.string"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/az.png"
                                }, {
                                    value: "number",
                                    label: RED._("common.type.number"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/09.png"
                                }, {
                                    value: "boolean",
                                    label: RED._("common.type.boolean"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/bool.png"
                                }, {
                                    value: "array",
                                    label: RED._("common.type.array"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/json.png"
                                }, {
                                    value: "buffer",
                                    label: RED._("common.type.buffer"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/bin.png"
                                }, {
                                    value: "object",
                                    label: RED._("common.type.object"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/json.png"
                                }, {
                                    value: "json",
                                    label: RED._("common.type.jsonString"),
                                    hasValue: false,
                                    icon: "red/images/typedInput/json.png"
                                }, {
                                    value: "undefined",
                                    label: RED._("common.type.undefined"),
                                    hasValue: false
                                }, {
                                    value: "null",
                                    label: RED._("common.type.null"),
                                    hasValue: false
                                }]
                            });
                        }

                        var valueField = null;
                        var numValueField = null;
                        var expValueField = null;
                        var btwnAndLabel = null;
                        var btwnValueField = null;
                        var btwnValue2Field = null;
                        var typeValueField = null;
                        //-->row
                        var finalspan = $('<span/>', {
                            style: "float: right;margin-top: 6px;"
                        }).appendTo(row);
                        finalspan.append(' &#8594; <span class="node-input-rule-index">' + i + '</span> ');
                        //input checkbox
                        var caseSensitive = $('<input/>', {
                            id: "node-input-rule-case-" + i,
                            class: "node-input-rule-case",
                            type: "checkbox",
                            style: "width:auto;vertical-align:top"
                        }).appendTo(row2);
                        $('<label/>', {
                            for: "node-input-rule-case-" + i,
                            style: "margin-left: 3px;"
                        }).text(caseLabel).appendTo(row2);
                        //////////////////////////////////////////////////////////interface data select1
                        selectPort.on("change", function() {
                            var portValue = selectPort.val();
                        });
                        selectPort.val(rule.p);
                        selectPort.change();
                        //////////////////////////////////////////////////////////rule data select2
                        selectField.on("change", function() {
                            var type = selectField.val();
                            if (valueField) {
                                valueField.typedInput('hide');
                            }
                            if (expValueField) {
                                expValueField.typedInput('hide');
                            }
                            if (numValueField) {
                                numValueField.typedInput('hide');
                            }
                            if (typeValueField) {
                                typeValueField.typedInput('hide');
                            }
                            if (btwnValueField) {
                                btwnValueField.typedInput('hide');
                            }
                            if (btwnValue2Field) {
                                btwnValue2Field.typedInput('hide');
                            }

                            if ((type === "btwn") || (type === "index")) {
                                if (!btwnValueField) {
                                    btwnValueField = createBtwnValueField();
                                }
                                btwnValueField.typedInput('show');
                            } else if ((type === "head") || (type === "tail")) {
                                if (!numValueField) {
                                    numValueField = createNumValueField();
                                }
                                numValueField.typedInput('show');
                            } else if (type === "jsonata_exp") {
                                if (!expValueField) {
                                    expValueField = createExpValueField();
                                }
                                expValueField.typedInput('show');
                            } else if (type === "istype") {
                                if (!typeValueField) {
                                    typeValueField = createTypeValueField();
                                }
                                typeValueField.typedInput('show');
                            } else if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else")) {
                                if (!valueField) {
                                    valueField = createValueField();
                                }
                                valueField.typedInput('show');
                            }
                            if (type === "regex") {
                                row2.show();
                                row3.hide();
                            } else if ((type === "btwn") || (type === "index")) {
                                row2.hide();
                                row3.show();
                                if (!btwnValue2Field) {
                                    btwnValue2Field = createBtwnValue2Field();
                                }
                                btwnValue2Field.typedInput('show');
                            } else {
                                row2.hide();
                                row3.hide();
                            }
                            resizeRule(container);

                        });
                        selectField.val(rule.t);
                        //Show and hide by choice
                        if ((rule.t == "btwn") || (rule.t == "index")) {
                            if (!btwnValueField) {
                                btwnValueField = createBtwnValueField();
                            }
                            btwnValueField.typedInput('value', rule.v);
                            btwnValueField.typedInput('type', rule.vt || 'num');

                            if (!btwnValue2Field) {
                                btwnValue2Field = createBtwnValue2Field();
                            }
                            btwnValue2Field.typedInput('value', rule.v2);
                            btwnValue2Field.typedInput('type', rule.v2t || 'num');
                        } else if ((rule.t === "head") || (rule.t === "tail")) {
                            if (!numValueField) {
                                numValueField = createNumValueField();
                            }
                            numValueField.typedInput('value', rule.v);
                            numValueField.typedInput('type', rule.vt || 'num');
                        } else if (rule.t === "istype") {
                            if (!typeValueField) {
                                typeValueField = createTypeValueField();
                            }
                            typeValueField.typedInput('value', rule.vt);
                            typeValueField.typedInput('type', rule.vt);
                        } else if (rule.t === "jsonata_exp") {
                            if (!expValueField) {
                                expValueField = createExpValueField();
                            }
                            expValueField.typedInput('value', rule.v);
                            expValueField.typedInput('type', rule.vt || 'jsonata');
                        } else if (typeof rule.v != "undefined") {
                            if (!valueField) {
                                valueField = createValueField();
                            }
                            valueField.typedInput('value', rule.v);
                            valueField.typedInput('type', rule.vt || 'str');
                        }
                        if (rule.case) {
                            caseSensitive.prop('checked', true);
                        } else {
                            caseSensitive.prop('checked', false);
                        }
                        selectField.change();
                        /////////////////Current output definition
                        var currentOutputs = JSON.parse(outputCount.val() || "{}");
                        currentOutputs[opt.hasOwnProperty('i') ? opt.i : opt._i] = i;
                        outputCount.val(JSON.stringify(currentOutputs));

                    },
                    //delete button event
                    removeItem: function(opt) {
                        //delete output port
                        var currentOutputs = JSON.parse(outputCount.val() || "{}");
                        if (opt.hasOwnProperty('i')) {
                            currentOutputs[opt.i] = -1;
                        } else {
                            delete currentOutputs[opt._i];
                        }
                        //delete data
                        var rules = $("#node-input-rule-container").editableList('items');
                        rules.each(function(i) {
                            $(this).find(".node-input-rule-index").html(i);
                            var data = $(this).data('data');
                            currentOutputs[data.hasOwnProperty('i') ? data.i : data._i] = i;
                        });
                        //Number of refresh ports
                        outputCount.val(JSON.stringify(currentOutputs));

                    },
                    resizeItem: resizeRule,
                    // Sort the list
                    sortItems: function(rules) {
                        var currentOutputs = JSON.parse(outputCount.val() || "{}");
                        var rules = $("#node-input-rule-container").editableList('items');
                        rules.each(function(i) {
                            $(this).find(".node-input-rule-index").html(i + 1);
                            var data = $(this).data('data');
                            currentOutputs[data.hasOwnProperty('i') ? data.i : data._i] = i;
                        });
                        outputCount.val(JSON.stringify(currentOutputs));
                    },
                    sortable: true,
                    removable: true
                });

                for (var i = 0; i < this.rules.length; i++) {
                    var rule = this.rules[i];
                    $("#node-input-rule-container").editableList('addItem', {
                        r: rule,
                        i: i
                    });
                }
            },
            oneditsave: function() {
                var rules = $("#node-input-rule-container").editableList('items');
                var node = this;
                node.rules = [];
                rules.each(function(i) {
                    var ruleData = $(this).data('data');
                    var rule = $(this);
                    var type = rule.find("select").next().val();
                    var typePort = rule.find("select").val();
                    var r = {
                        p: Number(typePort),
                        t: type
                    };
                    if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else")) {
                        if ((type === "btwn") || (type === "index")) {
                            r.v = rule.find(".node-input-rule-btwn-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-btwn-value").typedInput('type');
                            r.v2 = rule.find(".node-input-rule-btwn-value2").typedInput('value');
                            r.v2t = rule.find(".node-input-rule-btwn-value2").typedInput('type');
                        } else if ((type === "head") || (type === "tail")) {
                            r.v = rule.find(".node-input-rule-num-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-num-value").typedInput('type');
                        } else if (type === "istype") {
                            r.v = rule.find(".node-input-rule-type-value").typedInput('type');
                            r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
                        } else if (type === "jsonata_exp") {
                            r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');
                        } else {
                            r.v = rule.find(".node-input-rule-value").typedInput('value');
                            r.vt = rule.find(".node-input-rule-value").typedInput('type');
                        }
                        if (type === "regex") {
                            r.case = rule.find(".node-input-rule-case").prop("checked");
                        }
                    }
                    node.rules.push(r);

                });
                // console.log(node.rules);
                this.propertyType = $("#node-input-property").typedInput('type');


            },
            oneditresize: function(size) {
                var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
                var height = size.height;

                for (var i = 0; i < rows.length; i++) {
                    height -= $(rows[i]).outerHeight(true);
                }
                var editorRow = $("#dialog-form>div.node-input-rule-container-row");
                height -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom")));
                height += 16;
                $("#node-input-rule-container").editableList('height', height);
                /////////////////////////////////////////////////////////////////////
                $("#node-input-RD_Addr").on('focus', function() {}).on("change", function() {
                    ports_addr = [];
                    for (var i = 0; i < Number($("#node-input-RD_Num").val()); i++) {
                        ports_addr.push(Number($("#node-input-RD_Addr").val()) + i);
                    };
                    //button
                    if ($("#node-input-RD_Addr").val() && $("#node-input-RD_Num").val()) {
                        $('.red-ui-editableList-addButton').css("display", "block", "!important")
                    } else {
                        $('.red-ui-editableList-addButton').css("display", "none", "!important")
                    }
                });
                $("#node-input-RD_Num").on('focus', function() {}).on("change", function() {
                    ports_addr = [];
                    for (var i = 0; i < Number(this.value); i++) {
                        ports_addr.push(Number($("#node-input-RD_Addr").val()) + i);
                    };
                    // button
                    if ($("#node-input-RD_Addr").val() && $("#node-input-RD_Num").val()) {
                        $('.red-ui-editableList-addButton').css("display", "block", "!important")
                    } else {
                        $('.red-ui-editableList-addButton').css("display", "none", "!important")
                    }
                });
            }
        });
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////Read address
        RED.nodes.registerType('Read address', {
            color: "#8470FF",
            category: 'PLC',
            defaults: {
                // server
                server: {
                    value: "",
                    validate: RED.validators.regex(/^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/),
                    required: true
                },
                // The port number
                port: {
                    value: "",
                    validate: RED.validators.regex(/^\+?[1-9]\d*$/),
                    required: true

                },
                interval_tcp_time: {
                    value: 1000,
                    validate: RED.validators.regex(/^\+?[1-9]\d*$/),
                    required: true
                },
                out: {
                    value: "sit",
                    required: true
                },
                // Division rules
                splitc: {
                    value: "0",
                    required: true
                },
                // model
                model: {
                    value: "read",
                },
                //Read PLC start address
                RD_Addr: {
                    value: "",
                    validate: RED.validators.regex(/^\+?[1-9]\d*$/),
                },
                //Get the number of digits
                RD_Num: {
                    value: "",
                    validate: RED.validators.regex(/^\+?[1-9]\d*$/),
                },
            },
            inputs: 0,
            outputs: 0,
            outputLabels: function(index) {
                var rule = this.rules[index];
                var label = "";
            },
            icon: "font-awesome/fa-file-text-o",
            label: function() {
                return this.server + ": " + this.port || 'Keyence';
            },
            labelStyle: function() {
                return this.server ? "node_label_italic" : "";
            },
        });
    })();
</script>

<style>
    input,
    select {
        margin: 5px !important;
        padding: 2px !important;
        height: 25px !important;
    }
    
    li {
        list-style: none;
    }
    
    .form-row ul {
        margin: 0;
        padding: 0;
    }
    
    .border_bottom {
        padding-bottom: 10px;
        border-bottom: 1px solid #ccc;
    }
    
    #node-input-rule-container li:first-child {
        display: none;
        /* background-color: #ccc; */
    }
    
    button.red-ui-button-small {
        display: none;
    }
    
    ol li select {
        width: 20% !important;
    }
    
    .red-ui-typedInput-container {
        width: 45% !important;
    }
    
    .node-input-rule-container-row {
        width: 500px !important;
    }
</style>
